home *** CD-ROM | disk | FTP | other *** search
/ User's Choice Windows CD / User's Choice Windows CD (CMS Software)(1993).iso / misc1 / iv26_w30.zip / SOURCES / BOX.C < prev    next >
C/C++ Source or Header  |  1992-02-07  |  11KB  |  470 lines

  1. /*
  2.  * Copyright (c) 1987, 1988, 1989 Stanford University
  3.  *
  4.  * Permission to use, copy, modify, distribute, and sell this software and its
  5.  * documentation for any purpose is hereby granted without fee, provided
  6.  * that the above copyright notice appear in all copies and that both that
  7.  * copyright notice and this permission notice appear in supporting
  8.  * documentation, and that the name of Stanford not be used in advertising or
  9.  * publicity pertaining to distribution of the software without specific,
  10.  * written prior permission.  Stanford makes no representations about
  11.  * the suitability of this software for any purpose.  It is provided "as is"
  12.  * without express or implied warranty.
  13.  *
  14.  * STANFORD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
  15.  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
  16.  * IN NO EVENT SHALL STANFORD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
  17.  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
  18.  * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
  19.  * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
  20.  * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  21.  */
  22.  
  23. /*
  24.  * Basic composite object for interaction.
  25.  */
  26.  
  27. #include <InterViews/box.h>
  28. #include <InterViews/shape.h>
  29.  
  30. class BoxElement {
  31. public:
  32.     Interactor* child;
  33.     boolean visible;
  34.     BoxElement* next;
  35. };
  36.  
  37. class BoxDimension {
  38. public:
  39.     int natural;
  40.     int stretch;
  41.     int shrink;
  42. };
  43.  
  44. class BoxCanonical {
  45. public:
  46.     BoxDimension major;
  47.     BoxDimension minor;
  48. };
  49.  
  50. Box::Box () : (nil, nil) {
  51.     nelements = 0;
  52.     head = nil;
  53.     tail = nil;
  54. }
  55.  
  56. Box::~Box () {
  57.     register BoxElement* e;
  58.     register BoxElement* next;
  59.  
  60.     for (e = head; e != nil; e = next) {
  61.     next = e->next;
  62.     delete e->child;
  63.     delete e;
  64.     }
  65. }
  66.  
  67. void Box::Align (Alignment a) {
  68.     align = a;
  69. }
  70.  
  71. void Box::DoInsert (Interactor* i, boolean, Coord&, Coord&) {
  72.     register BoxElement* e;
  73.  
  74.     ++nelements;
  75.     e = new BoxElement;
  76.     e->child = i;
  77.     e->next = nil;
  78.     if (head == nil) {
  79.     head = e;
  80.     tail = e;
  81.     } else {
  82.     tail->next = e;
  83.     tail = e;
  84.     }
  85. }
  86.  
  87. void Box::DoChange (Interactor*) {
  88.     Reconfig();
  89. }
  90.  
  91. void Box::DoRemove (Interactor* i) {
  92.     register BoxElement* e, * prev;
  93.  
  94.     --nelements;
  95.     prev = nil;
  96.     for (e = head; e != nil; e = e->next) {
  97.     if (e->child == i) {
  98.         if (prev == nil) {
  99.         head = e->next;
  100.         } else {
  101.         prev->next = e->next;
  102.         }
  103.         if (e == tail) {
  104.         tail = prev;
  105.         }
  106.         delete e;
  107.         break;
  108.     }
  109.     prev = e;
  110.     }
  111.     ComputeShape(shape);
  112. }
  113.  
  114. void Box::Reconfig () {
  115.     ComputeShape(shape);
  116. }
  117.  
  118. void Box::Resize () {
  119.     register BoxElement* e;    /* box element */
  120.     Shape aggrshape;        /* combined shape of components */
  121.     BoxCanonical total;        /* components' shape along major axis */
  122.     int major, minor;        /* actual dimensions of box */
  123.     register int have;        /* how much box is willing to change */
  124.     register int need;        /* how much box needs to change to fit */
  125.     boolean grow;        /* true if stretching, false if shrinking */
  126.     BoxCanonical s;        /* element shape along major axis */
  127.     register int pos;        /* where to put next element on major axis */
  128.     register int len;        /* size of element along major axis */
  129.     register int n;        /* temporary variable */
  130.  
  131.     ComputeShape(&aggrshape);
  132.     GetActual(major, minor);
  133.     GetCanonical(&aggrshape, total);
  134.     n = total.major.natural;
  135.     if (major > n) {
  136.     /* more space than desired ==> stretch elements */
  137.     grow = true;
  138.     have = total.major.stretch;
  139.     need = min(major - n, have);
  140.     } else {
  141.     /* less (or equal) space than desired ==> (maybe) shrink elements */
  142.     grow = false;
  143.     have = total.major.shrink;
  144.     need = min(n - major, have);
  145.     }
  146.     pos = 0;
  147.     for (e = head; e != nil; e = e->next) {
  148.     GetCanonical(e->child->GetShape(), s);
  149.     len = s.major.natural;
  150.     if (have > 0) {
  151.         if (grow) {
  152.         n = int(double(s.major.stretch)*double(need)/double(have));
  153.         len += n;
  154.         have -= s.major.stretch;
  155.         } else {
  156.         n = int(double(s.major.shrink)*double(need)/double(have));
  157.         len -= n;
  158.         have -= s.major.shrink;
  159.         }
  160.         need -= n;
  161.     }
  162.     n = s.minor.natural;
  163.     if (n == 0) {
  164.         n = minor;
  165.     } else if (n > minor) {
  166.         n = max(n - s.minor.shrink, minor);
  167.     } else if (n < minor) {
  168.         n = min(n + s.minor.stretch, minor);
  169.     }
  170.     if (n > 0 && len > 0) {
  171.         e->visible = true;
  172.         PlaceElement(e->child, pos, len, minor, n);
  173.     } else {
  174.         e->visible = false;
  175.     }
  176.     pos += len;
  177.     }
  178. }
  179.  
  180. void Box::Draw () {
  181.     register BoxElement* e;
  182.  
  183.     for (e = head; e != nil; e = e->next) {
  184.     if (e->visible) {
  185.         e->child->Draw();
  186.     }
  187.     }
  188. }
  189.  
  190. void Box::GetComponents (Interactor** c, int nc, Interactor**& a, int& n) {
  191.     register BoxElement* e;
  192.     register Interactor** ap;
  193.  
  194.     n = nelements;
  195.     a = (n <= nc) ? c : new Interactor*[n];
  196.     ap = a;
  197.     for (e = head; e != nil; e = e->next) {
  198.     *ap++ = e->child;
  199.     }
  200. }
  201.  
  202. inline BoxElement* Box::Head () {
  203.     return head;
  204. }
  205.  
  206. /*
  207.  * Default virtuals.
  208.  */
  209.  
  210. void Box::ComputeShape (Shape*) {}
  211. void Box::GetActual (int& major, int& minor) {}
  212. void Box::GetCanonical (Shape*, BoxCanonical&) {}
  213. void Box::PlaceElement (Interactor*, Coord, int, int, int) {}
  214.  
  215. void HBox::Init () {
  216.     SetClassName("HBox");
  217.     align = Bottom;
  218.     shape->Rigid(0, 0, vfil, vfil);
  219. }
  220.     
  221. HBox::HBox () {
  222.     Init();
  223. }
  224.  
  225. HBox::HBox (Interactor* i1) {
  226.     Init();
  227.     Insert(i1);
  228. }
  229.  
  230. HBox::HBox (Interactor* i1, Interactor* i2) {
  231.     Init();
  232.     Insert(i1);
  233.     Insert(i2);
  234. }
  235.  
  236. HBox::HBox (Interactor* i1, Interactor* i2, Interactor* i3) {
  237.     Init();
  238.     Insert(i1);
  239.     Insert(i2);
  240.     Insert(i3);
  241. }
  242.  
  243. HBox::HBox (Interactor* i1, Interactor* i2, Interactor* i3, Interactor* i4) {
  244.     Init();
  245.     Insert(i1);
  246.     Insert(i2);
  247.     Insert(i3);
  248.     Insert(i4);
  249. }
  250.  
  251. HBox::HBox (
  252.     Interactor* i1, Interactor* i2, Interactor* i3, Interactor* i4,
  253.     Interactor* i5
  254. ) {
  255.     Init();
  256.     Insert(i1);
  257.     Insert(i2);
  258.     Insert(i3);
  259.     Insert(i4);
  260.     Insert(i5);
  261. }
  262.  
  263. HBox::HBox (
  264.     Interactor* i1, Interactor* i2, Interactor* i3, Interactor* i4,
  265.     Interactor* i5, Interactor* i6
  266. ) {
  267.     Init();
  268.     Insert(i1);
  269.     Insert(i2);
  270.     Insert(i3);
  271.     Insert(i4);
  272.     Insert(i5);
  273.     Insert(i6);
  274. }
  275.  
  276. HBox::HBox (
  277.     Interactor* i1, Interactor* i2, Interactor* i3, Interactor* i4,
  278.     Interactor* i5, Interactor* i6, Interactor* i7
  279. ) {
  280.     Init();
  281.     Insert(i1);
  282.     Insert(i2);
  283.     Insert(i3);
  284.     Insert(i4);
  285.     Insert(i5);
  286.     Insert(i6);
  287.     Insert(i7);
  288. }
  289.  
  290. void HBox::ComputeShape (register Shape* box) {
  291.     register BoxElement* e;
  292.     register Shape* s;
  293.     register int vmin, vmax;
  294.  
  295.     box->width = 0;
  296.     box->height = 0;
  297.     box->Rigid(0, 0, vfil, vfil);
  298.     vmin = -vfil;
  299.     vmax = vfil;
  300.     for (e = Head(); e != nil; e = e->next) {
  301.     s = e->child->GetShape();
  302.     box->width += s->width;
  303.     box->height = max(box->height, s->height);
  304.     box->hstretch += s->hstretch;
  305.     box->hshrink += s->hshrink;
  306.     vmin = max(s->height - s->vshrink, vmin);
  307.     vmax = min(s->height + s->vstretch, vmax);
  308.     }
  309.     box->vstretch = max(0, vmax - box->height);
  310.     box->vshrink = max(0, box->height - vmin);
  311. }
  312.  
  313. void HBox::GetActual (int& major, int& minor) {
  314.     major = xmax + 1;
  315.     minor = ymax + 1;
  316. }
  317.  
  318. void HBox::GetCanonical (register Shape* s, register BoxCanonical& b) {
  319.     b.major.natural = s->width;
  320.     b.major.shrink = s->hshrink;
  321.     b.major.stretch = s->hstretch;
  322.     b.minor.natural = s->height;
  323.     b.minor.shrink = s->vshrink;
  324.     b.minor.stretch = s->vstretch;
  325. }
  326.  
  327. void HBox::PlaceElement (Interactor* i, Coord x, int length, int size, int h) {
  328.     Coord x1, y1, x2, y2;
  329.  
  330.     x1 = x;
  331.     if (align == Top) {
  332.     y1 = size - h;
  333.     } else if (align == Center) {
  334.     y1 = (size - h) / 2;
  335.     } else /* Bottom */ {
  336.     y1 = 0;
  337.     }
  338.     x2 = x1 + length - 1;
  339.     y2 = y1 + h - 1;
  340.     Place(i, x1, y1, x2, y2);
  341. }
  342.  
  343. void VBox::Init () {
  344.     SetClassName("VBox");
  345.     align = Left;
  346.     shape->Rigid(hfil, hfil, 0, 0);
  347. }
  348.     
  349. VBox::VBox () {
  350.     Init();
  351. }
  352.  
  353. VBox::VBox (Interactor* i1) {
  354.     Init();
  355.     Insert(i1);
  356. }
  357.  
  358. VBox::VBox (Interactor* i1, Interactor* i2) {
  359.     Init();
  360.     Insert(i1);
  361.     Insert(i2);
  362. }
  363.  
  364. VBox::VBox (Interactor* i1, Interactor* i2, Interactor* i3) {
  365.     Init();
  366.     Insert(i1);
  367.     Insert(i2);
  368.     Insert(i3);
  369. }
  370.  
  371. VBox::VBox (Interactor* i1, Interactor* i2, Interactor* i3, Interactor* i4) {
  372.     Init();
  373.     Insert(i1);
  374.     Insert(i2);
  375.     Insert(i3);
  376.     Insert(i4);
  377. }
  378.  
  379. VBox::VBox (
  380.     Interactor* i1, Interactor* i2, Interactor* i3, Interactor* i4,
  381.     Interactor* i5
  382. ) {
  383.     Init();
  384.     Insert(i1);
  385.     Insert(i2);
  386.     Insert(i3);
  387.     Insert(i4);
  388.     Insert(i5);
  389. }
  390.  
  391. VBox::VBox (
  392.     Interactor* i1, Interactor* i2, Interactor* i3, Interactor* i4,
  393.     Interactor* i5, Interactor* i6
  394. ) {
  395.     Init();
  396.     Insert(i1);
  397.     Insert(i2);
  398.     Insert(i3);
  399.     Insert(i4);
  400.     Insert(i5);
  401.     Insert(i6);
  402. }
  403.  
  404. VBox::VBox (
  405.     Interactor* i1, Interactor* i2, Interactor* i3, Interactor* i4,
  406.     Interactor* i5, Interactor* i6, Interactor* i7
  407. ) {
  408.     Init();
  409.     Insert(i1);
  410.     Insert(i2);
  411.     Insert(i3);
  412.     Insert(i4);
  413.     Insert(i5);
  414.     Insert(i6);
  415.     Insert(i7);
  416. }
  417.  
  418. void VBox::ComputeShape (register Shape* box) {
  419.     register BoxElement* e;
  420.     register Shape* s;
  421.     register int hmin, hmax;
  422.  
  423.     box->width = 0;
  424.     box->height = 0;
  425.     box->Rigid(hfil, hfil, 0, 0);
  426.     hmin = -hfil;
  427.     hmax = hfil;
  428.     for (e = Head(); e != nil; e = e->next) {
  429.     s = e->child->GetShape();
  430.     box->width = max(box->width, s->width);
  431.     box->height += s->height;
  432.     box->vstretch += s->vstretch;
  433.     box->vshrink += s->vshrink;
  434.     hmin = max(s->width - s->hshrink, hmin);
  435.     hmax = min(s->width + s->hstretch, hmax);
  436.     }
  437.     box->hstretch = max(0, hmax - box->width);
  438.     box->hshrink = max(0, box->width - hmin);
  439. }
  440.  
  441. void VBox::GetActual (int& major, int& minor) {
  442.     major = ymax + 1;
  443.     minor = xmax + 1;
  444. }
  445.  
  446. void VBox::GetCanonical (register Shape* s, register BoxCanonical& b) {
  447.     b.major.natural = s->height;
  448.     b.major.shrink = s->vshrink;
  449.     b.major.stretch = s->vstretch;
  450.     b.minor.natural = s->width;
  451.     b.minor.shrink = s->hshrink;
  452.     b.minor.stretch = s->hstretch;
  453. }
  454.  
  455. void VBox::PlaceElement (Interactor* i, Coord y, int length, int size, int w) {
  456.     Coord x1, y1, x2, y2;
  457.  
  458.     if (align == Right) {
  459.     x1 = size - w;
  460.     } else if (align == Center) {
  461.     x1 = (size - w) / 2;
  462.     } else /* Left */ {
  463.     x1 = 0;
  464.     }
  465.     x2 = x1 + w - 1;
  466.     y2 = ymax - y;
  467.     y1 = y2 - length + 1;
  468.     Place(i, x1, y1, x2, y2);
  469. }
  470.